/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package model;

import java.io.BufferedOutputStream;
import java.io.IOException;
import java.net.Socket;

/**
 *
 * @author Asus
 */
public class Message {
    public static final int MSG_KEEP_ALIVE      = 0; //message utk ngecek socket masih idup atau gak
    public static final int MSG_FILEINFO        = 1; //message utk synchro
    public static final int MSG_FILEINFO_RESP   = 2; //message utk fileinfo dari server
    public static final int MSG_UPLOAD          = 3; //message dari client utk uplod file
    public static final int MSG_DOWNLOAD        = 4; //message dari client utk donlod
    public static final int MSG_DOWNLOAD_RESP   = 5; //message dari server tanda respon + file donlod
    public static final int MSG_DELETE          = 6; //message dari client utk delete
    
    private StringBuilder result;
    
    public Message(int messageType, Object[] parameter) {
        result = new StringBuilder();

        switch (messageType) {
            case MSG_KEEP_ALIVE:
                
                break;
            case MSG_FILEINFO:
                createMetadataMessage((String)parameter[0]);
                break;

            case MSG_FILEINFO_RESP:
                createMetadataResponseMessage((String)parameter[0], (byte[])parameter[1]);
                break;

            case MSG_UPLOAD:
                createUploadMessage((String)parameter[0], (byte[])parameter[1]);
                break;

            case MSG_DOWNLOAD:
                createDownloadMessage((String)parameter[0], (String)parameter[1]);
                break;

            case MSG_DOWNLOAD_RESP:
                createDownloadResponseMessage((String)parameter[0], (byte[])parameter[1]);
                break;
                
            case MSG_DELETE:
                createDeleteMessage((String)parameter[0]);
                break;
        }
    }

    public void createMetadataMessage(String remotePath) {
        result.append((char)MSG_FILEINFO);

        result.append((char)remotePath.length());
        result.append(remotePath);
    }

    public void createMetadataResponseMessage(String remotePath, byte[] binary) {
        result.append((char)MSG_FILEINFO_RESP);

        result.append((char)remotePath.length());
        result.append(remotePath);

        for (int i = 0; i < binary.length; ++i)
            result.append((char)binary[i]);
    }

    public void createUploadMessage(String remotePath, byte[] binary) {
        result.append((char)MSG_UPLOAD);

        result.append((char)remotePath.length());
        result.append(remotePath);

        for (int i = 0; i < binary.length; ++i)
            result.append((char)binary[i]);
    }

    public void createDownloadMessage(String localPath, String remotePath) {
        result.append((char)MSG_DOWNLOAD);

        result.append((char)localPath.length());
        result.append(localPath);
        result.append((char)remotePath.length());
        result.append(remotePath);
    }

    public void createDownloadResponseMessage(String localPath, byte[] binary) {
        result.append((char)MSG_DOWNLOAD_RESP);

        result.append((char)localPath.length());
        result.append(localPath);

        for (int i = 0; i < binary.length; ++i)
            result.append((char)binary[i]);
    }

    public void createDeleteMessage (String remotePath) {
        result.append((char)MSG_DELETE);

        result.append((char)remotePath.length());
        result.append(remotePath);
    }

    public static Object[] readMessage(int messageType, int messageLength, byte[] bin) {
        Object[] retval     = null;
        StringBuilder sb    = new StringBuilder();

        switch (messageType) {
            case MSG_KEEP_ALIVE:
                
                break;
            case MSG_FILEINFO:
                int pathLength = bin[0];
                retval = new Object[1];

                for (int i = 0; i < pathLength; ++i)
                    sb.append((char)bin[i + 1]);

                retval[0] = sb.toString();

                break;

            case MSG_FILEINFO_RESP:
                pathLength = bin[0];
                retval = new Object[2];

                for (int i = 0; i < pathLength; ++i)
                    sb.append((char)bin[i + 1]);

                retval[0] = sb.toString();
                byte[] binary = new byte[bin.length - pathLength - 1];

                for (int i = 0; i < binary.length; ++i)
                    binary[i] = bin[i + 1 + pathLength];

                retval[1] = binary;

                break;

            case MSG_UPLOAD:
                pathLength = bin[0];
                retval = new Object[2];

                for (int i = 0; i < pathLength; ++i)
                    sb.append((char)bin[i + 1]);

                retval[0] = sb.toString();
                binary = new byte[bin.length - pathLength - 1];

                for (int i = 0; i < binary.length; ++i)
                    binary[i] = bin[i + 1 + pathLength];

                retval[1] = binary;

                break;

            case MSG_DOWNLOAD:
                int localPathLength     = bin[0];
                int remotePathLength    = bin[1 + localPathLength];
                retval = new Object[2];

                for (int i = 0; i < localPathLength; ++i)
                    sb.append((char)bin[i + 1]);

                retval[0] = sb.toString();

                sb = new StringBuilder();

                int offset = 2 + localPathLength;
                for (int i = 0; i < remotePathLength; ++i)
                    sb.append((char)bin[i + offset]);

                retval[1] = sb.toString();

                break;

            case MSG_DOWNLOAD_RESP:
                pathLength = bin[0];
                retval = new Object[2];

                for (int i = 0; i < pathLength; ++i)
                    sb.append((char)bin[i + 1]);

                retval[0] = sb.toString();
                binary = new byte[bin.length - pathLength - 1];

                for (int i = 0; i < binary.length; ++i)
                    binary[i] = bin[i + 1 + pathLength];

                retval[1] = binary;
                
                break;

            case MSG_DELETE:
                remotePathLength = bin[0];
                System.out.println(remotePathLength);
                retval = new Object[1];

                for (int i = 0; i < remotePathLength; ++i)
                    sb.append((char)bin[i + 1]);

                retval[0] = sb.toString();

                break;
        }

        return retval;
    }
   
    public byte[] toSend() {
        String res = result.toString();
        int length = res.length() + 4;
        byte[] retval = new byte[length];

        // masukin messageType nya
        retval[0] = (byte)res.charAt(0);

        // masukin messageLength nya
        retval[1] = (byte)((length >> 24) % 256);
        retval[2] = (byte)((length >> 16) % 256);
        retval[3] = (byte)((length >> 8) % 256);
        retval[4] = (byte)((length) % 256);

        // masukin data nya
        for (int i = 5; i < length; ++i) {
            retval[i] = (byte)res.charAt(i - 4);
        }

        return retval;
    }

    public static void sendMessage(Socket socket, Message message) throws IOException {
        byte[] send     = message.toSend();

        BufferedOutputStream bos = new BufferedOutputStream(socket.getOutputStream());
        bos.write(send);
        bos.flush();
    }
    
}
